Set the window level depending on the type hint.
authorRichard Hult <richard@imendio.com>
Mon, 24 Jul 2006 10:46:21 +0000 (10:46 +0000)
committerRichard Hult <rhult@src.gnome.org>
Mon, 24 Jul 2006 10:46:21 +0000 (10:46 +0000)
2006-07-24  Richard Hult  <richard@imendio.com>

* gdk/quartz/gdkwindow-quartz.c (gdk_window_set_type_hint): Set the
window level depending on the type hint.

* gdk/quartz/gdkevents-quartz.c (gdk_keyboard_grab,
pointer_ungrab_internal): Only break the grab if the new window is
a different one.
(gdk_event_translate): Catch the case where the entire app loses
focus and break any grabs. Only do implicit grabs when the event
mask has both press and release.

* gdk/quartz/gdkkeys-quartz.c (translate_keysym):
* gdk/quartz/gdkselection-quartz.c:

        * gdk/quartz/GdkQuartzWindow.c
([GdkQuartzWindow -windowDidResignKey:]): Use this to update the
focus window instead of resignMain, fixes the case where other apps
uses focus follows mouse (like the terminal can).

gdk/quartz/GdkQuartzWindow.c
gdk/quartz/gdkevents-quartz.c
gdk/quartz/gdkkeys-quartz.c
gdk/quartz/gdkprivate-quartz.h
gdk/quartz/gdkselection-quartz.c
gdk/quartz/gdkwindow-quartz.c

index 3fc35f83ea908d8a4b5097d2b6735ae4e4bd2f24..6091e7a0b41079dfc06bf3baa2d0ec2eb45ecaa1 100644 (file)
@@ -62,7 +62,7 @@
   _gdk_quartz_update_focus_window (window, TRUE);
 }
 
--(void)windowDidResignMain:(NSNotification *)aNotification
+-(void)windowDidResignKey:(NSNotification *)aNotification
 {
   GdkWindow *window = [[self contentView] gdkWindow];
 
index d19ea8848e0ef9d87b0bab95d8fee718b569013a..98bb4e140c46bfd82990b44afd53836b022e5bc3 100644 (file)
@@ -2,7 +2,7 @@
  *
  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
  * Copyright (C) 1998-2002 Tor Lillqvist
- * Copyright (C) 2005 Imendio AB
+ * Copyright (C) 2005-2006 Imendio AB
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -369,8 +369,10 @@ gdk_keyboard_grab (GdkWindow  *window,
 
   if (_gdk_quartz_keyboard_grab_window)
     {
-      generate_grab_broken_event (_gdk_quartz_keyboard_grab_window,
-                                 TRUE, FALSE, window);
+      if (_gdk_quartz_keyboard_grab_window != window)
+       generate_grab_broken_event (_gdk_quartz_keyboard_grab_window,
+                                   TRUE, FALSE, window);
+      
       g_object_unref (_gdk_quartz_keyboard_grab_window);
     }
 
@@ -408,17 +410,17 @@ gdk_keyboard_grab_info_libgtk_only (GdkDisplay *display,
 }
 
 static void
-pointer_ungrab_internal (gboolean implicit)
+pointer_ungrab_internal (gboolean only_if_implicit)
 {
   if (!_gdk_quartz_pointer_grab_window)
     return;
 
-  if (pointer_grab_implicit && !implicit)
+  if (only_if_implicit && !pointer_grab_implicit)
     return;
 
   g_object_unref (_gdk_quartz_pointer_grab_window);
-
   _gdk_quartz_pointer_grab_window = NULL;
+
   /* FIXME: Send crossing events */
 }
 
@@ -563,16 +565,6 @@ apply_filters (GdkWindow  *window,
   return result;
 }
 
-/* Returns the current keyboard window */
-static GdkWindow *
-find_current_keyboard_window (void)
-{
-  if (_gdk_quartz_keyboard_grab_window && keyboard_grab_owner_events)
-    return _gdk_quartz_keyboard_grab_window;
-  
-  return current_keyboard_window;
-}
-
 /* This function checks if the passed in window is interested in the
  * event mask. If so, it's returned. If not, the event can be propagated
  * to its parent.
@@ -709,17 +701,16 @@ _gdk_quartz_update_focus_window (GdkWindow *window,
   if (got_focus && window == current_keyboard_window)
     return;
 
-  /* FIXME: Don't do this when grabbed */
-
-  if (!got_focus)
+  /* FIXME: Don't do this when grabbed? Or make GdkQuartzWindow
+   * disallow it in the first place instead?
+   */
+  
+  if (!got_focus && window == current_keyboard_window)
     {
-      if (window == current_keyboard_window)
-       {
          event = create_focus_event (current_keyboard_window, FALSE);
          append_event (event);
          g_object_unref (current_keyboard_window);
          current_keyboard_window = NULL;
-       }
     }
 
   if (got_focus)
@@ -997,7 +988,7 @@ _gdk_quartz_send_map_events (GdkWindow *window)
 GdkWindow *
 _gdk_quartz_get_mouse_window (void)
 {
-  if (_gdk_quartz_pointer_grab_window)
+  if (_gdk_quartz_pointer_grab_window && !pointer_grab_owner_events)
     return _gdk_quartz_pointer_grab_window;
   
   return current_mouse_window;
@@ -1150,6 +1141,8 @@ find_window_for_event (NSEvent *nsevent, gint *x, gint *y)
        
        return real_window;
       }
+      break;
+      
     case NSMouseEntered:
       {
        NSPoint point;
@@ -1163,9 +1156,9 @@ find_window_for_event (NSEvent *nsevent, gint *x, gint *y)
        mouse_window = _gdk_quartz_find_child_window_by_point (toplevel, point.x, point.y, x, y);
        
        synthesize_crossing_events (mouse_window, GDK_CROSSING_NORMAL, nsevent, *x, *y);
-
-       break;
       }
+      break;
+
     case NSMouseExited:
       synthesize_crossing_events (_gdk_root, GDK_CROSSING_NORMAL, nsevent, *x, *y);
       break;
@@ -1174,18 +1167,13 @@ find_window_for_event (NSEvent *nsevent, gint *x, gint *y)
     case NSKeyUp:
     case NSFlagsChanged:
       {
-       GdkWindow *keyboard_window;
        GdkEventMask event_mask;
-       GdkWindow *real_window;
 
        if (_gdk_quartz_keyboard_grab_window && !keyboard_grab_owner_events)
          return _gdk_quartz_keyboard_grab_window;
 
-       keyboard_window = find_current_keyboard_window ();
        event_mask = get_event_mask_from_ns_event (nsevent);
-       real_window = find_window_interested_in_event_mask (keyboard_window, event_mask, TRUE);
-
-       return real_window;
+       return find_window_interested_in_event_mask (current_keyboard_window, event_mask, TRUE);
       }
       break;
 
@@ -1214,24 +1202,18 @@ create_button_event (GdkWindow *window, NSEvent *nsevent,
     case NSRightMouseDown:
     case NSOtherMouseDown:
       type = GDK_BUTTON_PRESS;
-      button = convert_mouse_button_number ([nsevent buttonNumber]);
       break;
     case NSLeftMouseUp:
-      type = GDK_BUTTON_RELEASE;
-      button = 1;
-      break;
     case NSRightMouseUp:
-      type = GDK_BUTTON_RELEASE;
-      button = 3;
-      break;
     case NSOtherMouseUp:
       type = GDK_BUTTON_RELEASE;
-      button = convert_mouse_button_number ([nsevent buttonNumber]);
       break;
     default:
       g_assert_not_reached ();
     }
   
+  button = convert_mouse_button_number ([nsevent buttonNumber]);
+
   event = gdk_event_new (type);
   event->button.window = window;
   event->button.time = get_event_time (nsevent);
@@ -1410,7 +1392,38 @@ gdk_event_translate (NSEvent *nsevent)
        return TRUE;
     }
 
+  /* Catch the case where the entire app loses focus, and break any grabs. */
+  if ([nsevent type] == NSAppKitDefined)
+    {
+      if ([nsevent subtype] == NSApplicationDeactivatedEventType)
+       {
+         if (_gdk_quartz_keyboard_grab_window)
+           {
+             generate_grab_broken_event (_gdk_quartz_keyboard_grab_window,
+                                         TRUE, FALSE,
+                                         NULL);
+             g_object_unref (_gdk_quartz_keyboard_grab_window);
+             _gdk_quartz_keyboard_grab_window = NULL;
+           }
+
+         if (_gdk_quartz_pointer_grab_window)
+           {
+             generate_grab_broken_event (_gdk_quartz_pointer_grab_window,
+                                         FALSE, pointer_grab_implicit,
+                                         NULL);
+             g_object_unref (_gdk_quartz_pointer_grab_window);
+             _gdk_quartz_pointer_grab_window = NULL;
+           }
+       }
+    }
+
   window = find_window_for_event (nsevent, &x, &y);
+
+  /* FIXME: During owner_event grabs, we don't find a window when there is a
+   * click on a no-window widget, which makes popups etc still stay up. Need
+   * to figure out why that is.
+   */
+  
   if (!window)
     return FALSE;
 
@@ -1424,13 +1437,23 @@ gdk_event_translate (NSEvent *nsevent)
     case NSLeftMouseDown:
     case NSRightMouseDown:
     case NSOtherMouseDown:
-      /* Emulate implicit grab */
-      if (!_gdk_quartz_pointer_grab_window)
-       {
-         pointer_grab_internal (window, FALSE, GDK_WINDOW_OBJECT (window)->event_mask,
-                                NULL, NULL, TRUE);
-       }
+      {
+       GdkEventMask event_mask;
 
+       /* Emulate implicit grab, when the window has both PRESS and RELEASE
+        * in its mask, like X (and make it owner_events since that's what
+        * implicit grabs are like).
+        */
+       event_mask = (GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_RELEASE_MASK);
+       if (!_gdk_quartz_pointer_grab_window &&
+           (GDK_WINDOW_OBJECT (window)->event_mask & event_mask) == event_mask)
+         {
+           pointer_grab_internal (window, TRUE,
+                                  GDK_WINDOW_OBJECT (window)->event_mask,
+                                  NULL, NULL, TRUE);
+         }
+      }
+      
       event = create_button_event (window, nsevent, x, y);
       append_event (event);
       
index bee7cc8113973630f18819641648376c5925ed8d..c148c6d861ebd518b647b249a4e917c9c3f9387a 100644 (file)
@@ -497,15 +497,14 @@ gdk_keymap_lookup_key (GdkKeymap          *keymap,
   return 0;
 }
 
-
 #define GET_KEYVAL(keycode, group, level) (keyval_array[(keycode * KEYVALS_PER_KEYCODE + group * 2 + level)])
 
 static guint
 translate_keysym (guint           hardware_keycode,
                  gint            group,
                  GdkModifierType state,
-                 guint          *effective_group,
-                 guint          *effective_level)
+                 gint           *effective_group,
+                 gint           *effective_level)
 {
   gint level;
   guint tmp_keyval;
index 88a1ae533e55f292aafa3573c71c849ebf32eb2d..0116852333b3e47f7fdfd4ae1cc4d738bd13ca12 100644 (file)
@@ -1,6 +1,6 @@
 /* gdkwindow-quartz.c
  *
- * Copyright (C) 2005 Imendio AB
+ * Copyright (C) 2005-2006 Imendio AB
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -21,8 +21,6 @@
 #ifndef __GDK_PRIVATE_QUARTZ_H__
 #define __GDK_PRIVATE_QUARTZ_H__
 
-#include <config.h>
-
 #define GDK_QUARTZ_ALLOC_POOL NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]
 #define GDK_QUARTZ_RELEASE_POOL [pool release]
 
@@ -34,6 +32,8 @@
 
 #include "gdkinternals.h"
 
+#include <config.h>
+
 #define GDK_TYPE_GC_QUARTZ              (_gdk_gc_quartz_get_type ())
 #define GDK_GC_QUARTZ(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_GC_QUARTZ, GdkGCQuartz))
 #define GDK_GC_QUARTZ_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_GC_QUARTZ, GdkGCQuartzClass))
@@ -117,14 +117,14 @@ GdkWindow *_gdk_quartz_get_mouse_window     (void);
 void       _gdk_quartz_update_mouse_window  (GdkWindow *window);
 void       _gdk_quartz_update_cursor        (GdkWindow *window);
 
-GdkImage *_gdk_quartz_copy_to_image (GdkDrawable *drawable,
-                                    GdkImage    *image,
-                                    gint         src_x,
-                                    gint         src_y,
-                                    gint         dest_x,
-                                    gint         dest_y,
-                                    gint         width,
-                                    gint         height);
+GdkImage  *_gdk_quartz_copy_to_image (GdkDrawable *drawable,
+                                     GdkImage    *image,
+                                     gint         src_x,
+                                     gint         src_y,
+                                     gint         dest_x,
+                                     gint         dest_y,
+                                     gint         width,
+                                     gint         height);
 
 void _gdk_quartz_send_map_events (GdkWindow *window);
 
index ddc4f08b1d36611f789172357a0c4bc2cf1ce507..8724405a7ed61f9f5f311250258ad51c02509574 100644 (file)
@@ -23,6 +23,7 @@
 #include <config.h>
 
 #include "gdkselection.h"
+#include "gdkproperty.h"
 
 gboolean
 gdk_selection_owner_set_for_display (GdkDisplay *display,
index b5dfffa620c514f8ce39d151cd8650990f73d685..7bed32a08b0a7e83d580175f539a8aedae78b65f 100644 (file)
@@ -514,9 +514,6 @@ gdk_window_new (GdkWindow     *parent,
        else
          title = get_default_title ();
 
-       if (attributes->window_type == GDK_WINDOW_TEMP)
-         [impl->toplevel setLevel:NSPopUpMenuWindowLevel];
-
        gdk_window_set_title (window, title);
          
        if (draw_impl->colormap == gdk_screen_get_rgba_colormap (_gdk_screen))
@@ -635,8 +632,6 @@ show_window_internal (GdkWindow *window, gboolean raise)
   private = (GdkWindowObject *)window;
   impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
 
-  /* FIXME: We need to raise the window (move it to the top in the list) */
-
   if (impl->toplevel)
     {
       [impl->toplevel orderFront:nil];
@@ -1350,12 +1345,81 @@ void
 gdk_window_set_type_hint (GdkWindow        *window,
                          GdkWindowTypeHint hint)
 {
+  GdkWindowImplQuartz *impl;
+  gint                 level;
+  gboolean             shadow;
+  
   g_return_if_fail (GDK_IS_WINDOW (window));
 
   if (GDK_WINDOW_DESTROYED (window))
     return;
 
-  GDK_WINDOW_IMPL_QUARTZ (((GdkWindowObject *) window)->impl)->type_hint = hint;
+  impl = GDK_WINDOW_IMPL_QUARTZ (((GdkWindowObject *) window)->impl);
+
+  impl->type_hint = hint;
+
+  /* Match the documentation, only do something if we're not mapped yet. */
+  if (GDK_WINDOW_IS_MAPPED (window))
+    return;
+
+  switch (hint)
+    {
+    case GDK_WINDOW_TYPE_HINT_NORMAL:  /* Normal toplevel window */
+    case GDK_WINDOW_TYPE_HINT_DIALOG:  /* Dialog window */
+    case GDK_WINDOW_TYPE_HINT_TOOLBAR: /* Window used to implement toolbars */
+    case GDK_WINDOW_TYPE_HINT_DESKTOP: /* N/A */
+      level = NSNormalWindowLevel;
+      shadow = TRUE;
+      break;
+
+    case GDK_WINDOW_TYPE_HINT_DOCK:
+    case GDK_WINDOW_TYPE_HINT_UTILITY:
+      level = NSFloatingWindowLevel;
+      shadow = TRUE;
+      break;
+
+    case GDK_WINDOW_TYPE_HINT_MENU: /* Torn-off menu */
+      level = NSTornOffMenuWindowLevel;
+      shadow = TRUE;
+      break;
+      
+    case GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU: /* Menu from menubar */
+      level = NSSubmenuWindowLevel;
+      shadow = TRUE;
+      break;
+      
+    case GDK_WINDOW_TYPE_HINT_SPLASHSCREEN:
+      level = NSPopUpMenuWindowLevel;
+      shadow = TRUE;
+      break;
+      
+    case GDK_WINDOW_TYPE_HINT_POPUP_MENU:
+    case GDK_WINDOW_TYPE_HINT_COMBO:
+      level = NSPopUpMenuWindowLevel;
+      shadow = TRUE;
+      break;
+      
+    case GDK_WINDOW_TYPE_HINT_NOTIFICATION:
+    case GDK_WINDOW_TYPE_HINT_TOOLTIP:
+      level = NSStatusWindowLevel;
+      shadow = TRUE;
+      break;
+
+    case GDK_WINDOW_TYPE_HINT_DND:
+      level = NSPopUpMenuWindowLevel;
+      shadow = FALSE;
+      break;
+
+    default:
+      level = NSNormalWindowLevel;
+      shadow = FALSE;
+      break;
+    }
+
+  /* Note: The shadow should probably be handled in a theme:
+     [impl->toplevel setHasShadow:shadow];
+  */
+  [impl->toplevel setLevel:level];
 }
 
 GdkWindowTypeHint